package com.handinfo.util;

import java.util.Vector;

import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

import com.handinfo.engine.AbstractGameScreen;

public final class TextBox
{

	public static final boolean IS_PLUS = true;

	public static final int[] gameButtonsDefault = { AbstractGameScreen.GK_UP,
			AbstractGameScreen.GK_DOWN, AbstractGameScreen.GK_LEFT,
			AbstractGameScreen.GK_RIGHT | AbstractGameScreen.GK_A };

	public int[] gameButtons = gameButtonsDefault;

	public static final int GAME_BUTTON_ROLL_UP = 0;

	public static final int GAME_BUTTON_ROLL_DOWN = 1;

	public static final int GAME_BUTTON_PAGE_UP = 2;

	public static final int GAME_BUTTON_PAGE_DOWN = 3;

	public final static int ADJUST_NONE = 0;

	public final static int ADJUST_WIDTH = 1;

	public final static int ADJUST_HEIGHT = 1 << 1;

	public final static int ADJUST_HEIGHT_MAX = 1 << 2;

	public final static int STYLE_TEXTWIN = 0;

	public final static int STYLE_DIALOG = 1;

	public final static int STYLE_AUTOTEXTWIN = 2;

	public int style;

	private boolean hasScrollBar; // 是否有滚动条

	public int width, height;

	private int WIDTH, HEIGHT;

	public String[] texts;

	private int flipHeight;

	public static final int ROW_GAP = 2; // 行与行之间的间隙

	private int rowHeight = AbstractGameScreen.FONT_H + ROW_GAP;;

	private int totalHeight;

	public static final int SCROLL_BAR_WIDTH = 5; // 滚动条宽度

	public int maxWidth;// 有效显示宽度

	public int backColor;

	public int textColor;

	public int shadowColor;

	public int scrollBarColor = 0xff666666; // 滚动条颜色

	public int scrollBarSlipColor = 0xffaaaaaa; // 滚动条滑块颜色

	public int adjustSizeFlag; // 是否根据文本情况调整窗口大小的标志,可为ADJUST_NONE,或ADJUST_WIDTH,ADJUST_HEIGHT的组合

	public int textStyle = Tools.TEXT_STYLE_NORMAL; // 文字样式

	public int textPosStyle = Tools.LEFT_TOP; // 文字对齐方式

	public int scrollSpeed = 1;

	private int step = 0;

	private static final int STEP_GAP = 5;

	private int pos;

	private int[][] script;

	public int fontSize = Font.SIZE_SMALL;

	public TextBox(int style, int width, int height, int textColor,
			int shadowColor, int backColor, int adjustSizeFlag)
	{
		this.style = style;
		WIDTH = width;
		HEIGHT = height;
		this.textColor = textColor;
		this.shadowColor = shadowColor;
		this.backColor = backColor;
		this.adjustSizeFlag = adjustSizeFlag;
		if (IS_PLUS) {
			script = new int[0][];
		}
	}

	public void setSize(int width, int height)
	{
		WIDTH = width;
		HEIGHT = height;
	}

	/**
	 * 设置字体大小，必须在设置文字前设置，默认为小字体
	 * 
	 * @param newFontSize
	 */
	// public final void setFont(int newFontSize) {
	// if (font.getSize() != newFontSize) {
	// font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, newFontSize);
	// }
	// }
	/**
	 * 设置按键 buttons[0]:上滚一行 buttons[1]:下滚一行 buttons[2]:上翻一页 buttons[3]:下翻一页
	 * 
	 * @param buttons
	 * 长度为4的数组
	 */
	public final void setButton(int[] buttons)
	{
		if (Tools.DEBUG) {
			if (buttons.length < 4) {
				System.out
						.println("setButton(int[] button) buttons are not enough");
			}
		}
		gameButtons = buttons;
	}

	/**
	 * 设置文本窗口显示的文本，根据文本确定显示的行列数以及宽和高，其中宽度不能超过maxWidth。
	 * 文本将被切割成一个String数组，数组的元素数目就是文本窗口的行数
	 * 
	 * @param text
	 * 需要显示的文本
	 */
	public void setText(String text)
	{
		// int oldFontSize = AbstractGameScreen.s_font.getSize();
		clearText();
		rowHeight = AbstractGameScreen.FONT_H + ROW_GAP;

		Vector tmpTexts = new Vector();
		maxWidth = WIDTH;
		hasScrollBar = false;

		if (IS_PLUS) {
			StringBuffer tmpString = new StringBuffer();
			int textStyle = this.textStyle;
			int textColor = this.textColor;
			int shadowColor = this.shadowColor;
			int textLen = text.length();
			for (int p = 0; p < textLen; p++) {
				if (text.charAt(p) == '\n' || text.charAt(p) == '|') {
					tmpTexts.addElement(tmpString.toString());
					tmpString.setLength(0);
				}
				else if (text.charAt(p) == '`') {
					int len = script.length;
					int[][] tmp = script;
					script = new int[len + 1][];
					System.arraycopy(tmp, 0, script, 0, len);
					script[len] = new int[5];
					script[len][0] = tmpTexts.size();
					script[len][1] = tmpString.length();
					char c = text.charAt(p + 1);
					switch (c) {
						case 'c': {
							textColor = Integer.valueOf(
									text.substring(p + 2, p + 8), 16).intValue() | 0xff000000;
							p += 7;
							break;
						}
						case 'b': {
							shadowColor = Integer.valueOf(
									text.substring(p + 2, p + 8), 16).intValue() | 0xff000000;
							p += 7;
							break;
						}
						case 's': {
							switch (text.charAt(p + 2)) {
								case 'N': {
									textStyle = Tools.TEXT_STYLE_NORMAL;
									break;
								}
								case 'S': {
									textStyle = Tools.TEXT_STYLE_SHADOW;
									break;
								}
								case 'A': {
									textStyle = Tools.TEXT_STYLE_AROUND;
									break;
								}
								case 'C': {
									textStyle = Tools.TEXT_STYLE_CROSS;
									break;
								}
							}
							p += 2;
							break;
						}
					}
					script[len][2] = textStyle;
					script[len][3] = textColor;
					script[len][4] = shadowColor;
				}
				else {
					tmpString.append(text.charAt(p));
					int newWidth = AbstractGameScreen.s_font.stringWidth(tmpString.toString());
					if (newWidth > maxWidth) {
						tmpString.setLength(tmpString.length() - 1);
						p--;
						tmpTexts.addElement(tmpString.toString());
						tmpString.setLength(0);
					}
				}
				if (p == textLen - 1) {
					tmpTexts.addElement(tmpString.toString());
				}
				if (style == STYLE_TEXTWIN && !hasScrollBar && (adjustSizeFlag & ADJUST_HEIGHT_MAX) == 0) {
					int tmpH = tmpTexts.size() * rowHeight;
					if (tmpH > HEIGHT || tmpH == HEIGHT && p < textLen - 1) {
						hasScrollBar = true;
						p = -1;
						maxWidth = WIDTH - SCROLL_BAR_WIDTH;
						tmpTexts.removeAllElements();
						tmpString.setLength(0);
						script = new int[0][];
					}
				}
			}
			// tmpTexts.addElement(tmpString.toString());
		}
		else {
			int start = 0;
			int textLen = text.length();
			for (int p = 0; p < textLen; p++) {
				if (text.charAt(p) == '\n' || text.charAt(p) == '|') {
					tmpTexts.addElement(text.substring(start, p));
					start = p + 1;
				}
				else {
					int newWidth = AbstractGameScreen.s_font.stringWidth(text
							.substring(start, p + 1));
					if (newWidth > maxWidth) {
						tmpTexts.addElement(text.substring(start, p));
						newWidth = 0;
						start = p;
						p--;
					}
				}
				if (p == textLen - 1) {
					tmpTexts.addElement(text.substring(start, textLen));
				}
				if (style == STYLE_TEXTWIN && !hasScrollBar
						&& (adjustSizeFlag & ADJUST_HEIGHT_MAX) == 0) {
					int tmpH = tmpTexts.size() * rowHeight;
					if (tmpH > HEIGHT || tmpH == HEIGHT && p < textLen - 1) {
						hasScrollBar = true;
						p = -1;
						start = 0;
						maxWidth = WIDTH - SCROLL_BAR_WIDTH;
						tmpTexts.removeAllElements();
					}
				}
			}

		}
		text = null;
		texts = new String[tmpTexts.size()];
		tmpTexts.copyInto(texts);
		tmpTexts = null;

		totalHeight = texts.length * rowHeight;

		// 调整窗口大小:
		// 1.宽度
		// 如果只有一行文本且宽度没达到指定的窗口宽,则调节宽度至文本宽度+2倍间隙宽
		// 或如果分成多行文本但每行中由于有数字或英文而使都达不到指定的宽度,则调节窗口宽度至文本行最大宽度+2倍间隙宽
		// 2.高度
		// 如果显示的行数的总高度不能达到指定的窗口高度,则调节窗口高度至:文本行高*maxShowRows+间隙宽,其中文本行高=字高+行间间隙
		if ((adjustSizeFlag & ADJUST_WIDTH) != 0) {
			maxWidth = 0;
			for (int i = 0; i < texts.length; i++) {
				int lineWidth = AbstractGameScreen.s_font.stringWidth(texts[i]);
				if (lineWidth > maxWidth) {
					maxWidth = lineWidth;
				}
			}
			width = maxWidth;
			if (hasScrollBar) {
				width += SCROLL_BAR_WIDTH;
			}
		}
		else {
			width = WIDTH;
		}
		if ((adjustSizeFlag & ADJUST_HEIGHT_MAX) != 0) {
			height = totalHeight;
			flipHeight = totalHeight;
		}
		else {
			flipHeight = ((HEIGHT) / rowHeight) * rowHeight;
			if ((adjustSizeFlag & ADJUST_HEIGHT) != 0) {
				height = totalHeight <= HEIGHT ? totalHeight : flipHeight;
			}
			else {
				height = HEIGHT;
			}
		}

		pos = style == STYLE_AUTOTEXTWIN ? -height : 0;

		// HLUtil.setFont(oldFontSize);
	}

	public void clearText()
	{
		if (IS_PLUS) {
			if (texts != null) {
				script = null;
				script = new int[0][];
				texts = null;
			}
		}
		else {
			texts = null;
		}
	}

	// 显示文字
	public void render(Graphics g, int x, int y)
	{
		if (texts == null)
			return;
		Tools.drawRectAlpha(g, x, y, width, height, backColor);
		// int stringHeight = font.getHeight();
		// int rowHeight = HLUtil.stringHeight + ROW_GAP;
		int cx = g.getClipX();
		int cy = g.getClipY();
		int cw = g.getClipWidth();
		int ch = g.getClipHeight();
		g.clipRect(x, y, maxWidth, height);

		int ty, firstRow;
		if (style == STYLE_AUTOTEXTWIN && pos < 0) {
			ty = -pos;
			firstRow = 0;
		}
		else {
			firstRow = pos / rowHeight;
			ty = -pos % rowHeight;
		}
		int th = style == STYLE_DIALOG ? flipHeight : height;

		// int oldFontSize = AbstractGameScreen.s_font.getSize();
		// HLUtil.setFont(fontSize);
		if (IS_PLUS) {
			int textStyle = this.textStyle;
			int textColor = this.textColor;
			int shadowColor = this.shadowColor;
			int last = script.length - 1;
			for (; last >= 0; last--) {
				if (script[last][0] < firstRow) {
					textStyle = script[last][2];
					textColor = script[last][3];
					shadowColor = script[last][4];
					break;
				}
			}
			last++;

			for (int i = firstRow; i < texts.length && ty < th; i++, ty += rowHeight) {
				int subStart = 0;
				int tx = x;
				for (int m = last; m < script.length; m++) {
					if (script[m][0] > i) {
						break;
					}
					if (script[m][0] == i) {
						String s = texts[i].substring(subStart, script[m][1]);
						subStart = script[m][1];
						last = m;
						Tools.drawStringAdjustable(g, s, textColor,
								shadowColor, tx, y + ty, maxWidth,
								AbstractGameScreen.FONT_H, textStyle,
								textPosStyle);
						tx += AbstractGameScreen.s_font.stringWidth(s);
						textStyle = script[m][2];
						textColor = script[m][3];
						shadowColor = script[m][4];
					}
				}
				Tools.drawStringAdjustable(g,
						texts[i].substring(subStart, texts[i].length()),
						textColor, shadowColor, tx, y + ty, maxWidth,
						AbstractGameScreen.FONT_H, textStyle, textPosStyle);

			}
		}
		else {
			for (int i = firstRow; i < texts.length && ty < th; i++, ty += rowHeight) {
				// if (i >= 0) {
				Tools.drawStringAdjustable(g, texts[i], textColor, shadowColor,
						x, y + ty, maxWidth, AbstractGameScreen.FONT_H,
						textStyle, textPosStyle);
				// }
			}
		}
		// HLUtil.setFont(oldFontSize);
		g.setClip(cx, cy, cw, ch);

		if (hasScrollBar) {
			// 画滚动条
//			int sbX = x + width - SCROLL_BAR_WIDTH;
//			int sbY = y + SCROLL_BAR_WIDTH - 1;// gapWidth;
//			int sbHeight = height - (SCROLL_BAR_WIDTH - 1 << 1);// (gapWidth <<
//			// 1) ;
//
//			Tools.drawRectRimAlpha(g, sbX, y, SCROLL_BAR_WIDTH,
//					SCROLL_BAR_WIDTH, 1, scrollBarColor);
//			Tools.drawRectRimAlpha(g, sbX, y + height - SCROLL_BAR_WIDTH,
//					SCROLL_BAR_WIDTH, SCROLL_BAR_WIDTH, 1, scrollBarColor);
//			Tools.drawRectRimAlpha(g, sbX, sbY, SCROLL_BAR_WIDTH, sbHeight, 1,
//					scrollBarColor);
//			// renderRoundRect(g, sbX, y, SCROLL_BAR_WIDTH, SCROLL_BAR_WIDTH);
//			//
//			// renderRoundRect(g, sbX, y + height - SCROLL_BAR_WIDTH,
//			// SCROLL_BAR_WIDTH, SCROLL_BAR_WIDTH);
//			//
//			// renderRoundRect(g, sbX, sbY, SCROLL_BAR_WIDTH, sbHeight);
//
//			int slipHeight = (sbHeight - 2) * height / totalHeight;
//			if (slipHeight < 1) {
//				slipHeight = 1;
//			}
//			int slipPos = (sbHeight - 2 - slipHeight) * pos
//					/ (totalHeight - height) + 1;
//			// if(slipPos != 1) {
//			Tools.drawRectAlpha(g, sbX + (SCROLL_BAR_WIDTH >> 1), y
//					+ ((SCROLL_BAR_WIDTH >> 1) - 1), 1, 1, scrollBarSlipColor);
//			Tools.drawRectAlpha(g, sbX + ((SCROLL_BAR_WIDTH >> 1) - 1), y
//					+ (SCROLL_BAR_WIDTH >> 1), 1, 1, scrollBarSlipColor);
//			Tools.drawRectAlpha(g, sbX + ((SCROLL_BAR_WIDTH >> 1) + 1), y
//					+ (SCROLL_BAR_WIDTH >> 1), 1, 1, scrollBarSlipColor);
//			// }
//			// if(slipPos + slipHeight != sbHeight - 1) {
//			Tools.drawRectAlpha(g, sbX + (SCROLL_BAR_WIDTH >> 1), y + height
//					- (SCROLL_BAR_WIDTH >> 1), 1, 1, scrollBarSlipColor);
//			Tools.drawRectAlpha(g, sbX + ((SCROLL_BAR_WIDTH >> 1) - 1), y
//					+ height - ((SCROLL_BAR_WIDTH >> 1) + 1), 1, 1,
//					scrollBarSlipColor);
//			Tools.drawRectAlpha(g, sbX + ((SCROLL_BAR_WIDTH >> 1) + 1), y
//					+ height - ((SCROLL_BAR_WIDTH >> 1) + 1), 1, 1,
//					scrollBarSlipColor);
//			// HLUtil.drawRectAlpha(g, sbX + 1, y + height - gapWidth + 1,
//			// scrollBarWidth - 2, gapWidth - 2, scrollBarSlipColor);
//			// }
//			int slipWidth = SCROLL_BAR_WIDTH - 2;
//			Tools.drawRectAlpha(g, sbX + 1, sbY + slipPos, slipWidth,
//					slipHeight, scrollBarSlipColor);
		}

	}

	public void renderAdjustable(Graphics g, int rectX, int rectY,
			int rectWidth, int rectHeight, int posStyle)
	{
		render(g, Tools.getPosAdjustableH(width, rectX, rectWidth, posStyle),
				Tools.getPosAdjustableV(height, rectY, rectHeight, posStyle)//
		);
	}

	// private void renderRoundRect(Graphics g, int x, int y, int w, int h) {
	// g.drawLine(x + 1, y, x + w - 2, y);
	// g.drawLine(x + 1, y + h - 1, x + w - 2, y + h - 1);
	// g.drawLine(x, y + 1, x, y + h - 2);
	// g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 2);
	// }

	int oldPos;

	int oldY;

	public boolean logic()
	{
		if (texts == null || texts.length == 0)
			return true;
		switch (style) {
			case STYLE_TEXTWIN: {
				// if (GameScreen.SUPPORT_POINTER) {
				// if (GameScreen.isInputDown(SubScreen.GAME_POINTER)) {
				// oldY = GameScreen.curPointerY;
				// oldPos = pos;
				// } else if (GameScreen.isInputHold(SubScreen.GAME_POINTER)) {
				// pos = -GameScreen.curPointerY + oldY + oldPos;
				// }
				// }

				if (step > STEP_GAP
						&& AbstractGameScreen
								.haveKeyHold(gameButtons[GAME_BUTTON_ROLL_UP])
						|| AbstractGameScreen
								.haveKeyPressed(gameButtons[GAME_BUTTON_ROLL_UP])) {
					pos -= rowHeight;
				}
				else if (step > STEP_GAP
						&& AbstractGameScreen
								.haveKeyHold(gameButtons[GAME_BUTTON_ROLL_DOWN])
						|| AbstractGameScreen
								.haveKeyPressed(gameButtons[GAME_BUTTON_ROLL_DOWN])) {
					pos += rowHeight;
				}
				else if (step > STEP_GAP
						&& AbstractGameScreen
								.haveKeyHold(gameButtons[GAME_BUTTON_PAGE_UP])
						|| AbstractGameScreen
								.haveKeyPressed(gameButtons[GAME_BUTTON_PAGE_UP])) {
					pos -= flipHeight;

				}
				else if (step > STEP_GAP
						&& AbstractGameScreen
								.haveKeyHold(gameButtons[GAME_BUTTON_PAGE_DOWN])
						|| AbstractGameScreen
								.haveKeyPressed(gameButtons[GAME_BUTTON_PAGE_DOWN])) {
					if (pos >= totalHeight - height) {
						return true;
					}
					else {
						pos += flipHeight;
					}
				}
				if (AbstractGameScreen.haveKeyHold(gameButtons[GAME_BUTTON_ROLL_UP]
						| gameButtons[GAME_BUTTON_ROLL_DOWN]
						| gameButtons[GAME_BUTTON_PAGE_UP]
						| gameButtons[GAME_BUTTON_PAGE_DOWN])) {
					step++;
				}
				else {
					step = 0;
				}

				if (pos + height > totalHeight) {
					pos = totalHeight - height;
				}
				if (pos < 0) {
					pos = 0;
				}
				break;
			}
			case STYLE_DIALOG: {
				if (AbstractGameScreen
						.haveKeyPressed(gameButtons[GAME_BUTTON_PAGE_DOWN])) {
					if (pos + flipHeight < totalHeight) {
						pos += flipHeight;
					}
					else {
						return true;
					}
				}
				break;
			}
			case STYLE_AUTOTEXTWIN: {
				if (AbstractGameScreen
						.haveKeyHold(gameButtons[GAME_BUTTON_ROLL_UP])) {
				}
				else if (AbstractGameScreen
						.haveKeyHold(gameButtons[GAME_BUTTON_ROLL_DOWN])) {
					pos += scrollSpeed << 2;
				}
				else {
					pos += scrollSpeed;
				}
				if (pos >= totalHeight) {
					pos = -height;
					return true;
				}
			}
		}
		return false;
	}
}
